<template>

  <div class="map">
    <router-link to="/">tree</router-link>
    |
    <router-link to="/gisMap">map</router-link>
    |
    <router-link to="/threeD">3D scene</router-link>

    <div class="gisMap" id="gisMap"></div>
    <!--    <div id="coordsWidget" class="esri-widget esri-component" ref="coordsWidget">{{coordsWidget}}</div>-->
  </div>
</template>

<script>
import {loadModules} from 'esri-loader'

export default {
  name: 'GisMap',
  data() {
    return {
      // coordsWidget: '',
      sketch: {},
      activeGraphic: {},
      featureLayer: {},
      bufferGraphic: {},
      Graphic: {},
      geometryEngine:{},
      lineGraphic:{},
      textGraphic:{}
    }
  },
  mounted() {
    // lazy load the required ArcGIS API for JavaScript modules and CSS
    loadModules(['esri/Map',
      'esri/views/MapView',
      'esri/widgets/BasemapToggle',
      'esri/widgets/BasemapGallery',
      'esri/layers/FeatureLayer',
      'esri/layers/Layer',
      'esri/Basemap',
      'esri/layers/VectorTileLayer',
      'esri/layers/TileLayer',
      'esri/WebMap',
      'esri/widgets/Legend',
      'esri/widgets/ScaleBar',
      'esri/widgets/CoordinateConversion',
      'esri/layers/GraphicsLayer',
      'esri/widgets/Sketch',
      'esri/Graphic',
      'esri/widgets/Locate',
      'esri/widgets/Track',
      'esri/widgets/Compass',
      'esri/geometry/geometryEngine'
    ], {css: true})
        .then(([ArcGISMap, MapView, BasemapToggle, BasemapGallery, FeatureLayer, Layer, Basemap, VectorTileLayer, TileLayer, WebMap, Legend, ScaleBar, CoordinateConversion, GraphicsLayer, Sketch, Graphic, Locate, Track, Compass, geometryEngine]) => {
//自定义basemap
          // const basemap = new Basemap({
          //   baseLayers: [
          //     new TileLayer({
          //       portalItem: {
          //         id: "1b243539f4514b6ba35e7d995890db1d" // World Hillshade
          //       }
          //     }),
          //     new VectorTileLayer({
          //       portalItem: {
          //         id: "d2ff12395aeb45998c1b154e25d680e5" // Forest and Parks Canvas
          //       },
          //       opacity: 0.5
          //     })
          //   ]
          // });
          this.Graphic = Graphic
          this.geometryEngine = geometryEngine
          const graphicsLayer = new GraphicsLayer()
          this.featureLayer = new FeatureLayer({
            url: 'https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails_Styled/FeatureServer/0'
          })

//正常声明map
          const map = new ArcGISMap({
            basemap: 'topo-vector',
            // basemap:basemap,
            layers: graphicsLayer
          })
          this.view = new MapView({
            container: 'gisMap',
            map: map,
            center: [-118.805, 34.027],
            zoom: 13
          })
          map.add(this.featureLayer)

//设置素描工具
          this.sketch = new Sketch({
            view: this.view,
            layer: graphicsLayer
          })
          this.view.ui.add(this.sketch, 'top-right')
          this.sketchStyleChange(this.sketch)

//设置 point graphic
          const pointKeys = {
            point: {
              type: 'point',
              latitude: 34.0005930608889,
              longitude: -118.80657463861
            },
            simpleMarkerSymbol: {
              type: 'simple-marker',
              color: [226, 119, 40],
              outline: {
                color: [225, 225, 225],
                width: 1
              }
            }
          }
          const pointGraphic = new Graphic({
            geometry: pointKeys.point,
            symbol: pointKeys.simpleMarkerSymbol
          })
          graphicsLayer.add(pointGraphic)

//设置 line graphic
          const lineKeys = {
            polyline: {
              type: 'polyline',
              paths: [
                [-118.821527826096, 34.0139576938577],
                [-118.814893761649, 34.0080602407843],
                [-118.808878330345, 34.0016642996246]
              ]
            },
            simpleLineSymbol: {
              type: 'simple-line',
              color: [226, 119, 40],
              width: 2,
              style: 'dash'
            }
          }
          const polylineGraphic = new Graphic({
            geometry: lineKeys.polyline,
            symbol: lineKeys.simpleLineSymbol
          })
          graphicsLayer.add(polylineGraphic)

//设置 polygon graphic
          const polygonKeys = {
            polygon: {
              type: 'polygon',
              rings: [
                [-118.818984489994, 34.0137559967283],
                [-118.806796597377, 34.0215816298725],
                [-118.791432890735, 34.0163883241613],
                [-118.79596686535, 34.008564864635],
                [-118.808558110679, 34.0035027131376]
              ]
            },
            simpleFillSymbol: {
              type: 'simple-fill',
              color: [227, 139, 79, 0.8],
              outline: {
                color: 'green',
                width: 1
              }
            }
          }
          const polygonGraphic = new Graphic({
            geometry: polygonKeys.polygon,
            symbol: polygonKeys.simpleFillSymbol
          })
          graphicsLayer.add(polygonGraphic)

//设置locate
//           var locate = new Locate({
//             view: this.view,
//             useHeadingEnabled: false,  //不改变地图的旋转
//             goToOverride: function (view, options) {  //为小部件提供自定义缩放功能
//               options.target.scale = 1500; // Override the default map scale
//               return view.goTo(options.target);
//             }
//           });
//           this.view.ui.add(locate, "top-left");

//设置Track your location 通常只使用一个地理定位小部件，因此删除了Locate小部件并添加Track小部件。
//           var track = new Track({
//             view: this.view,
//             graphic: new Graphic({
//               symbol: {
//                 type: 'simple-marker',
//                 size: '12px',
//                 color: 'green',
//                 outline: {
//                   color: '#efefef',
//                   width: '1.5px'
//                 }
//               }
//             }),
//             useHeadingEnabled: true // Don't change orientation of the map
//           })
//           this.view.ui.add(track, 'top-left')
//设置compass useHeadingEnabled要为true
//           var compass = new Compass({
//             view: this.view
//           })
//           this.view.ui.add(compass, 'top-left')

//webMap设置
//           const webMap = new WebMap({
//             portalItem: {id: '41281c51f9de45edaf1c8ed44bb10e30'}
//           })
//
//           this.view = new MapView({
//             container: 'gisMap',
//             map: webMap //设置的效果等价于以下三行
//             // map: map,
//             // center: [-118.805, 34.027],
//             // zoom: 3
//           })

//自定义小部件
          // this.view.watch('stationary', (isStationary) => {
          //   this.showCoordinates(this.view.center)
          // })
          // this.view.on('pointer-move',(event)=>{
          //   this.showCoordinates(this.view.toMap({x: event.x, y: event.y}))
          // })
          // this.view.ui.add(this.$refs.coordsWidget,'bottom-right')

//CoordinateConversion坐标变换
          const coordinateConversion = new CoordinateConversion({
            view: this.view
          })
          this.view.ui.add(coordinateConversion, 'bottom-right')

//设置说明和缩放比例widgets
          // const legend = new Legend({
          //   view:this.view
          // })
          // const scalebar = new ScaleBar({
          //   view:this.view
          // })
          // this.view.ui.add(legend,'top-right')
          // this.view.ui.add(scalebar,'bottom-left')

//开启底图选择
          // const basemapToggle = new BasemapToggle({
          //   view: this.view,
          //   nextBasemap: "satellite"
          // });
          // this.view.ui.add(basemapToggle, "bottom-right");
          // const basemapGallery = new BasemapGallery({
          //   view: this.view,
          //   source: {
          //     portal: {
          //       url: "https://www.arcgis.com",
          //       // useVectorBasemaps: true // Load vector tile basemaps
          //       useVectorBasemaps: false // Load raster tile basemaps
          //     }
          //   }
          // });
          // this.view.ui.add(basemapGallery, "top-right");

//trailheadsLayer设置
//           const trailheadsRenderer = {
//             type: 'simple',
//             symbol: {
//               type: 'picture-marker',
//               url: 'http://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png',
//               width: '18px',
//               height: '18px'
//             }
//           }
//           const trailheadsLabels = {
//             symbol: {
//               type: 'text',
//               color: '#FFFFFF',
//               haloColor: '#5E8D74',
//               haloSize: '2px',
//               font: {
//                 size: '12px',
//                 family: 'Noto Sans',
//                 style: 'italic',
//                 weight: 'normal'
//               }
//             },
//             labelPlacement: 'above-center',
//             labelExpressionInfo: {
//               expression: '$feature.TRL_NAME'
//             }
//           }
//           const popupTrailheads = {
//             title: '{TRL_NAME}',
//             content:
//                 '<b>City:</b> {CITY_JUR}<br><b>Cross Street:</b> {X_STREET}<br><b>Parking:</b> {PARKING}<br><b>Elevation:</b> {ELEV_FT} ft'
//           }
//           const trailheadsLayer = new FeatureLayer({
//             url: 'https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0',
//             renderer: trailheadsRenderer,
//             labelingInfo: [trailheadsLabels],
//             outFields: ['TRL_NAME', 'CITY_JUR', 'X_STREET', 'PARKING', 'ELEV_FT'],
//             popupTemplate: popupTrailheads
//           })
//           map.add(trailheadsLayer)

//trailsLayer设置
//           const trailsRenderer = {
//             type: 'simple',
//             symbol: {
//               color: '#BA55D3',
//               type: 'simple-line',
//               style: 'solid'
//             },
//             visualVariables: [
//               {
//                 type: 'size',
//                 field: 'ELEV_GAIN',
//                 minDataValue: 0,
//                 maxDataValue: 2300,
//                 minSize: '3px',
//                 maxSize: '7px'
//               }
//             ]
//           }
//           const trailsLayer = new FeatureLayer({
//             url: 'https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0',
//             // definitionExpression: 'ELEV_GAIN < 250',
//             renderer: trailsRenderer,
//             outFields: ['*'],
//             opacity: 0.75,
//             popupTemplate: {
//               // Enable a popup
//               title: '{TRL_NAME}', // Show attribute value
//               content: 'The trail elevation gain is {ELEV_GAIN} ft.' // Display text in pop-up
//             }
//           })
//           map.add(trailsLayer, 0)
//
//           // var featureLayer = new FeatureLayer({
//           //   url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails_Styled/FeatureServer/0",
//           //   outFields: ["*"], // Return all fields so it can be queried client-side
//           //   popupTemplate: {
//           //     // Enable a popup
//           //     title: "{TRL_NAME}", // Show attribute value
//           //     content: "The trail elevation gain is {ELEV_GAIN} ft." // Display in pop-up
//           //   }
//           // });
//           // map.add(featureLayer);
//
//           //filter a featureLayer
//           const sqlExpressions = [
//             'TRL_ID > 0',
//             'TRL_ID = 0',
//             'USE_BIKE = \'Yes\'',
//             'USE_BIKE = \'No\'',
//             'ELEV_GAIN < 1000',
//             'ELEV_GAIN > 1000',
//             'TRL_NAME = \'California Coastal Trail\''
//           ]
//           const selectFilter = document.createElement('select')
//           selectFilter.setAttribute('class', 'esri-widget esri-select')
//           selectFilter.setAttribute('style', 'width: 275px; font-family: Avenir Next W00; font-size: 1em;')
//           sqlExpressions.forEach((sql) => {
//             const option = document.createElement('option')
//             option.value = sql
//             option.innerHTML = sql
//             selectFilter.appendChild(option)
//           })
//           this.view.ui.add(selectFilter, 'top-right')
//           //server-side filter function
//           const setFeatureLayerFilter = (expression) => {
//             trailsLayer.definitionExpression = expression
//           }
//           //client-side filter function
//           const setFeatureLayerViewFilter = (expression) => {
//             this.view.whenLayerView(trailsLayer).then((featureLayerView) => {
//               featureLayerView.effect = {
//                 filter: {where: expression},
//                 excludedEffect: 'opacity(40%)'
//               }
//
//             })
//           }
//           selectFilter.addEventListener('change', (event) => {
//             setFeatureLayerViewFilter(event.target.value)
//           })
//
//           let highlight
//           this.view.whenLayerView(trailsLayer).then((featureLayerView) => {
//             this.view.on('pointer-move', (event) => {
//               // console.log(event)
//               this.view.hitTest(event).then((response)=> {
//                 // Only return features for the feature layer
//                 const graphic = response.results.filter((result)=> {
//                   return result.graphic.layer === trailsLayer
//                 })[0]
//                 let feature
//                 if (graphic) {
//                   feature = graphic.graphic
//                   if (highlight) {
//                     highlight.remove()
//                   }
//                   // Highlight feature
//                     highlight = featureLayerView.highlight(feature)
//                 }
//
//               })
//             })
//           })

          // const bikeTrailsRenderer = {
          //   type: "simple",
          //   symbol: {
          //     type: "simple-line",
          //     style: "short-dot",
          //     color: "#FF91FF",
          //     width: "1px"
          //   }
          // };
          // const bikeTrails = new FeatureLayer({
          //   url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0",
          //   renderer: bikeTrailsRenderer,
          //   definitionExpression: "USE_BIKE = 'YES'"
          // });
          // map.add(bikeTrails, 1);

//parksLayer设置
//           function createFillSymbol(value, color) {
//             return {
//               value: value,
//               symbol: {
//                 color: color,
//                 type: 'simple-fill',
//                 style: 'solid',
//                 outline: {
//                   style: 'none'
//                 }
//               },
//               label: value
//             }
//           }
//
//           const openSpacesRenderer = {
//             type: 'unique-value',
//             field: 'TYPE',
//             uniqueValueInfos: [
//               createFillSymbol('Natural Areas', '#9E559C'),
//               createFillSymbol('Regional Open Space', '#A7C636'),
//               createFillSymbol('Local Park', '#149ECE'),
//               createFillSymbol('Regional Recreation Park', '#ED5151')
//             ]
//           }
//           const parksLayer = new FeatureLayer({
//             url: 'https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0',
//             renderer: openSpacesRenderer,
//             opacity: 0.2
//           })
//           map.add(parksLayer, 0)

//通过layers设置trailheadsLayer,trailLayer,parksLayer
//           function addLayer(layerItemPromise, index) {
//             return layerItemPromise.then(function (layer) {
//               //Limit layer features with a SQL definition expression
//               layer.when(()=>{
//                 if (layer.title === 'Trails_Styled_Popups'){layer.definitionExpression = "ELEV_GAIN < 250";}
//               })
//               map.add(layer, index);
//             });
//           }
//           const trailheadsPortalItem = Layer.fromPortalItem({
//             portalItem: {id: "33fc2fa407ab40f9add12fe38d5801f5"}
//           });
//           const trailsPortalItem = Layer.fromPortalItem({
//             portalItem: {id: "52a162056a2d48409fc3b3cbb672e7da"}
//           });
//           const parkPortalItem = Layer.fromPortalItem({
//             portalItem:{id:'83cf97eea04e4a699689c250dd07b975'}
//           })
//
//           addLayer(trailheadsPortalItem, 2)
//           .then(addLayer(trailsPortalItem,1))
//           .then(addLayer(parkPortalItem,0));
          this.view.on('pointer-move', (event) => {
            this.findNearestGraphic(event).then((graphic)=>{
              if (graphic) {
                this.activeGraphic = graphic;
                const buffer = geometryEngine.geodesicBuffer(this.activeGraphic.geometry, 0.25, "miles");
                this.drawBuffer(buffer);
              }
            });
            this.intersect()
          })
        })
  },
  methods: {
    // showCoordinates(pt) {
    //   this.coordsWidget =
    //       'Lat/Lon: ' + pt.x.toFixed(3) +'/'+ pt.y.toFixed(3)+
    //       ' | Scale: 1:'+Math.round(this.view.scale*1)/1+
    //       ' | Zoom: '+this.view.zoom
    // },


    sketchStyleChange(sketch) {
      const stroke = {
        color: [255, 0, 0],
        width: 1,
      }
      const fillColor = [255, 255, 255, 0.5]
      const pointSymbol = sketch.viewModel.pointSymbol
      pointSymbol.color = fillColor
      pointSymbol.outline = stroke
      pointSymbol.size = 8
      const polylineSymbol = sketch.viewModel.polylineSymbol
      polylineSymbol.color = stroke.color
      polylineSymbol.width = stroke.width
      const polygonSymbol = sketch.viewModel.polygonSymbol
      polygonSymbol.color = fillColor
      polygonSymbol.outline = stroke
    },

    findNearestGraphic(event) {
      return this.view.hitTest(event).then((response) => {
        let graphic
        // Get the Trail graphics only
        if (response.results.length) {
          const graphics = response.results.filter((result) => {
            return result.graphic.layer === this.featureLayer
          })
          if (graphics.length > 0) {graphic = graphics[0].graphic}
        }
        //Only return new graphics are found
        if (graphic) {
          if (!this.activeGraphic || !this.activeGraphic.attributes || this.activeGraphic.attributes.OBJECTID != graphic.attributes.OBJECTID) {
            return graphic
          } else {return null}
        } else {return null}
      })
    },

    drawBuffer(bufferGeometry) {
      this.view.graphics.remove(this.bufferGraphic)
      this.bufferGraphic = new this.Graphic({
        geometry: bufferGeometry,
        symbol: {
          type: 'simple-fill',
          color: 'rgba(0,0,0,0)',
          outline: {
            color: 'rgba(0,0,0,.5)',
            width: 1
          }
        }
      })
      this.view.graphics.add(this.bufferGraphic)
    },
    intersect(){
      if (this.bufferGraphic && this.bufferGraphic.geometry) {
        const cursorPoint = this.view.toMap(event);
        const intersects = this.geometryEngine.intersects(this.bufferGraphic.geometry, cursorPoint);
        const symbol = this.bufferGraphic.symbol.clone();
        if (intersects) {
          symbol.color = "rgba(0,0,0,.15)"; // Highlight
        } else {
          symbol.color = "rgba(0,0,0,0)"; // Transparent
        }
        this.bufferGraphic.symbol = symbol;
        //寻找最近的点
        const vertexResult = this.geometryEngine.nearestVertex(this.bufferGraphic.geometry, cursorPoint)
        const closestPoint = vertexResult.coordinate
        this.drawLine(cursorPoint,closestPoint)
        //计算出距离并显示
        const distance = this.geometryEngine.geodesicLength(this.lineGraphic.geometry,'miles')
        this.drawText(cursorPoint,distance)
      }
    },
    drawLine(point,point2){
      this.view.graphics.remove(this.lineGraphic)
      this.lineGraphic = new this.Graphic({
        geometry:{
          type:'polyline',
          paths: [
              [point.longitude,point.latitude],
              [point2.longitude,point2.latitude]
          ]
        },
        smybol:{
          type:'simple-line',
          color:'#666',
          width:1
        }
      })
      this.view.graphics.add(this.lineGraphic)
    },
    drawText(point,distance){
      this.view.graphics.remove(this.textGraphic)
      this.textGraphic = new this.Graphic({
        geometry:point,
        symbol:{
          type:'text',
          text:distance.toFixed(2)+'miles',
          color:'red',
          font:{size:12},
          haloColor:'white',
          haloSize:1
        }
      })
      this.view.graphics.add(this.textGraphic)
    }
  },
  beforeDestroy() {
    if (this.view) {
      // destroy the map view
      this.view.destroy()
    }
  },

}
</script>

<style scoped lang="scss">
.map {
  .gisMap {
    margin-top: 20px;
    width: 1200px;
    height: 80vh;
  }

  .esri-widget {
    padding: 10px;
  }
}
</style>